﻿//-----------------------------------------------------------------------
// <copyright file="ClipboardModule.Copy.cs" company="Nathan Miller">
// Copyright (c) Nathan Miller.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
//-----------------------------------------------------------------------
namespace App.Modules.Clipboard
{
    using System.Collections.Generic;
    using App.Modules.Scene;
    using TileTool.Clipboard;
    using TileTool.DataBag;
    using TileTool.Scene;
    using TileTool.Scene.Entity;

    /// <summary>
    /// Application clipboard module copy specific code. 
    /// </summary>
    public partial class ClipboardModule
    {
        #region Methods - Private

        /// <summary>
        /// Set clipboard data to the currently selected objects.
        /// </summary>
        private void SetClipboardDataToSelection()
        {
            SceneModule sceneModule = GetModule<SceneModule>();
            ISceneManager scene = sceneModule.Scene;
            IEntityCollection selection = scene.Selection;

            if (selection.Count == 0)
            {
                return;
            }

            DataBag infoBag = new DataBag();
            ClipboardData data = new ClipboardData();
            IDictionary<string, IDataBag> dict = data.DataDictionary;
            IEntityCollection copyObjects = this.BuildCopyObjects(selection);
            ClipboardDataInfo dataInfo = new ClipboardDataInfo();

            dataInfo.ObjectCount = copyObjects.Count;
            dataInfo.DataType = (int)ClipboardDataType.Entity;

            int i = 0;
            foreach (IEntity entity in copyObjects)
            {
                string name = string.Format(ObjectKeyFormat, i);

                dict.Add(name, entity.Bag);

                ++i;
            }
            
            dict.Add(InfoBagKey, DataBagObjectSerialization.ObjectToDataBag(dataInfo));

            this.clipboard.SetData(data);
        }

        /// <summary>
        /// Build the collection of objects that we are going to copy. For objects
        /// with children we will recurse down into them so that they are copied
        /// along with their parents.
        /// </summary>
        /// <param name="selection">Currently selected objects in the scene.</param>
        /// <returns>Returns the collection of objects to copy.</returns>
        private IEntityCollection BuildCopyObjects(IEntityCollection selection)
        {
            IEntityCollection copyObjects = new EntityCollection();

            this.BuildCopyObjectsRecurse(selection, copyObjects);

            return copyObjects;
        }

        /// <summary>
        /// Recursively build the collection of objects to copy.
        /// </summary>
        /// <param name="objects">Objects to iterate over</param>
        /// <param name="destObjects">Destination collection for objects to copy.</param>
        private void BuildCopyObjectsRecurse(IEntityCollection objects, IEntityCollection destObjects)
        {
            foreach (IEntity entity in objects)
            {
                destObjects.Add(entity);

                if (entity.Children.Count != 0)
                {
                    this.BuildCopyObjectsRecurse(entity.Children, destObjects);
                }
            }
        }

        #endregion
    }
}
